package demoMod.invincibleOne.patches;

import com.evacipated.cardcrawl.modthespire.lib.ByRef;
import com.evacipated.cardcrawl.modthespire.lib.SpireInsertPatch;
import com.evacipated.cardcrawl.modthespire.lib.SpirePatch;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.core.AbstractCreature;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.monsters.AbstractMonster;
import demoMod.invincibleOne.interfaces.MonsterBloodiedHook;
import demoMod.invincibleOne.interfaces.MonsterGainBlockHook;
import demoMod.invincibleOne.interfaces.MonsterRegenOrMaxHPApplyHook;

import java.util.ArrayList;
import java.util.stream.Collectors;

public class AbstractCreaturePatch {
    @SpirePatch(
            clz = AbstractCreature.class,
            method = "addBlock"
    )
    public static class PatchAddBlock {
        @SpireInsertPatch(rloc = 1, localvars = {"tmp"})
        public static void Insert(AbstractCreature creature, int blockAmount, @ByRef float[] _tmp) {
            for (AbstractCreature creature1 : AbstractDungeon.getMonsters().monsters.stream().filter(m -> !m.isDeadOrEscaped()).collect(Collectors.toList())) {
                for (MonsterGainBlockHook gainBlockHook : creature1.powers.stream().filter(power -> power instanceof MonsterGainBlockHook).map(power -> (MonsterGainBlockHook) power).collect(Collectors.toList())) {
                    _tmp[0] = gainBlockHook.onGainedBlock(creature, _tmp[0]);
                }
            }
        }
    }

    @SpirePatch(
            clz = AbstractCreature.class,
            method = "increaseMaxHp"
    )
    public static class PatchIncreaseMaxHp {
        public static void Postfix(AbstractCreature creature, int amount, boolean showEffect) {
            if (creature instanceof AbstractMonster && amount > 0) {
                float tmp = amount;
                for (AbstractCreature creature1 : AbstractDungeon.getMonsters().monsters.stream().filter(m -> !m.isDeadOrEscaped()).collect(Collectors.toList())) {
                    for (MonsterRegenOrMaxHPApplyHook maxHPApplyHook : creature1.powers.stream().filter(power -> power instanceof MonsterRegenOrMaxHPApplyHook).map(power -> (MonsterRegenOrMaxHPApplyHook) power).collect(Collectors.toList())) {
                        tmp = maxHPApplyHook.onMaxHpIncreased(creature, tmp);
                    }
                }
                for (MonsterRegenOrMaxHPApplyHook maxHPApplyHook : AbstractDungeon.player.masterDeck.group.stream().filter(card -> card instanceof MonsterRegenOrMaxHPApplyHook).map(card -> (MonsterRegenOrMaxHPApplyHook) card).collect(Collectors.toList())) {
                    tmp = maxHPApplyHook.onMaxHpIncreased(creature, tmp);
                }
                creature.maxHealth -= amount;
                creature.maxHealth += Math.ceil(tmp);
                creature.heal((int) Math.ceil(tmp) - amount, false);
            }
        }
    }

    @SpirePatch(
            clz = AbstractCreature.class,
            method = "healthBarUpdatedEvent"
    )
    public static class PatchHealthBarUpdatedEvent {
        public static void Postfix(AbstractCreature creature) {
            if (creature instanceof AbstractMonster) {
                AbstractMonster m = (AbstractMonster) creature;
                for (AbstractCard card : AbstractDungeon.player.masterDeck.group) {
                    if (card instanceof MonsterBloodiedHook) {
                        MonsterBloodiedHook hook = (MonsterBloodiedHook) card;
                        if (m.currentHealth > m.maxHealth / 2 && m.isBloodied) {
                            hook.onMonsterNotBloodied(m);
                        } else if (m.currentHealth <= m.maxHealth / 2 && !m.isBloodied) {
                            hook.onMonsterBloodied(m);
                        }
                    }
                }
                m.isBloodied = m.currentHealth <= m.maxHealth / 2;
            }
        }
    }
}
